/**
 * @class   wosh::MessageContentGeneric
 * @brief   Base abstract class for contents of a Message
 *
 ****************************************************************************
 * @version $Id: MessageContentGeneric.h 2863 2010-08-07 04:28:58Z alex $
 * @author  Alessandro Polo
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/

#ifndef __WOSH_Core_MessageContentGeneric_H__
 #define __WOSH_Core_MessageContentGeneric_H__

 #include <woshDefs.h>
 #include <core/MessageContent.h>
 #include <core/Variant.h>
 #include <core/Utilities.h>


namespace wosh {

class MessageContentGeneric : public MessageContent
 {
	WOSH_CLASSNAME(wosh::MessageContentGeneric)
	WOSH_COMPARE_RTTI(wosh::MessageContentGeneric)

	public:
		MessageContentGeneric()
			: MessageContent(), content(NULL) { }

		MessageContentGeneric( const std::string& context, ISerializable* data = NULL )
			: MessageContent(), contentContext(context), content(data) {
		 }

		MessageContentGeneric( const MessageContentGeneric& m )
			: MessageContent(), contentContext(m.contentContext), content(NULL) {
			if ( m.content != NULL )
				this->content = m.content->clone();
		 }

		virtual ~MessageContentGeneric() {
			if ( this->content != NULL )
				delete this->content; this->content = NULL;
		 }

	public:
		MessageContentGeneric& operator=(const MessageContentGeneric& m) {
			if (this == &m) return *this; // same object?
			this->contentContext = m.contentContext;
			if ( this->content != NULL )
				delete this->content; this->content = NULL;
			if ( m.content != NULL )
				this->content = m.content->clone();
			return *this;
		 }

		bool operator==(const MessageContentGeneric& other) const {
			if ( this->getType() != other.getType() ) return false;
			if ( this->contentContext != other.contentContext ) return false;
			if ( this->content != NULL ) {
				if ( this->content->compare(other.content) != WOSH_COMPARE_RET_IDEMPOTENT )
					return false;
			 }
			else if ( other.content != NULL )
				return false;
			return true;
		 }

		virtual bool operator!=(const MessageContentGeneric &other) const { return !(*this == other); }


	public:
		inline const std::string& getContentContext() const				{ return this->contentContext; }

		/**
		 * @brief  Check if contains any Data object
		 * @return true when data object is set (not NULL), false else.
		 */
		inline bool hasData() const 									{ return (this->content != NULL); }

		/**
		 * @brief  Get the data object (ISerializable abstraction) associated with the content.
		 * @return constant pointer to the data object. May be NULL.
		 */
		inline const ISerializable* getData() const				{ return this->content; }
		/**
		 * @brief  Get the data object (ISerializable abstraction) associated with the content.
		 * @return pointer to the data object (editable). May be NULL.
		 */
		inline ISerializable* getData()							{ return this->content; }


	public:
		/**
		 * @brief  Set the data object (ISerializable abstraction) associated with the content.
		 * @param [in] data the data object associated with the content. May be NULL.
		 * @see    setContent()
		 */
		inline void setData( ISerializable* data ) {
			if ( this->content != NULL )
				delete this->content;
			this->content = data;
		 }


	public:
		inline std::string getDataClassName() const {
			if ( this->content == NULL || this->content->getClassName() == NULL )
				return "";
			return std::string(this->content->getClassName());
		 }


//@}
/** @name Serialization interface
 * @{
 ******************************************************************************/
	public:
		virtual inline std::string toString() const {
			if ( this->content == NULL )
				return Utilities::format("%s[%s,NULL]", getClassName(), this->contentContext.c_str() );
			return Utilities::format("%s(%s)[%s,%s]", getClassName(), getDataClassName().c_str(), this->contentContext.c_str(), this->content->toString().c_str() );
		 }
		virtual inline bool updateHash( DataHashContext* hash_context ) const {
			if ( hash_context == NULL ) return false;
			bool ret = true;
			ret = hash_context->update( this->contentContext ) & ret;
			if ( this->content != NULL )
				ret = this->content->updateHash(hash_context) & ret;
			return ret;
		 }
//@}

	protected:
		virtual void clear() {
			this->contentContext.clear();
			setData(NULL);
		 }

	protected:
		std::string contentContext;
		ISerializable* content;


}; // class def


}; // namespace wosh


#endif //__WOSH_Core_MessageContentGeneric_H__
